package com.mgq.java8.forkjoin;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.stream.LongStream;

/**
 * <b>功能：</b>ForkJoin求和<br>
 * <b>Copyright TCSL</b>
 * <li>版本&nbsp;&nbsp;&nbsp;&nbsp;修改日期&nbsp;&nbsp;&nbsp;&nbsp;部　　门&nbsp;&nbsp;&nbsp;&nbsp;作　者&nbsp;&nbsp;&nbsp;&nbsp;变更内容</li><hr>
 * <li>v1.0&nbsp;&nbsp;&nbsp;&nbsp;20220415&nbsp;&nbsp;营业后台&nbsp;&nbsp;&nbsp;&nbsp;马广奇&nbsp;&nbsp;&nbsp;&nbsp;创建类</li>
 * <br><br>
 *
 * @author 马广奇
 * @version 2022-04-15 13:08
 */
public class ForkJoinSumCalculator extends RecursiveTask<Long> {
    private final long numbers[];
    private final int start;
    private final int end;

    private final int THRESHOLD = 10_000;

    /**
     * 公共构造函数,用于创建主任务
     */
    public ForkJoinSumCalculator(long[] numbers) {
        this(numbers, 0, numbers.length);
    }

    /**
     * 私有构造函数,用于创建子任务
     */
    private ForkJoinSumCalculator(long[] numbers, int start, int end) {
        this.numbers = numbers;
        this.start = start;
        this.end = end;
    }


    @Override
    protected Long compute() {
        int length = end - start;
        if (length <= THRESHOLD) {
            return computeSequentially();
        }
        ForkJoinSumCalculator left = new ForkJoinSumCalculator(numbers, start, start + length / 2);
        left.fork();
        ForkJoinSumCalculator right = new ForkJoinSumCalculator(numbers, start + length / 2, end);
        Long rightResult = right.compute();
        return left.join() + rightResult;
    }

    private long computeSequentially() {

        long sum = 0;
        for (int i = start; i < end; i++) {
            sum += numbers[i];
        }
        return sum;
    }

    public static long forkJoinSum(int n) {
        long[] numbers = LongStream.rangeClosed(1, n).toArray();
        ForkJoinSumCalculator forkJoinSumCalculator = new ForkJoinSumCalculator(numbers);
        return new ForkJoinPool().invoke(forkJoinSumCalculator);
    }

    public static void main(String[] args) {
        System.out.println(forkJoinSum(100000));
        System.out.println(forkJoinSum(3));

        int a =10;
       Runnable r1= ()->{
          final int b = a;
           System.out.println(a);
        };
    }
}
